package com.siyoumi.app.test.sys;

import com.siyoumi.component.XApp;
import com.siyoumi.component.XRedis;
import com.siyoumi.component.XRedisLock;
import com.siyoumi.config.SysConfig;
import com.siyoumi.test.TestController;
import com.siyoumi.test.annotation.TestClass;
import com.siyoumi.test.annotation.TestFunc;
import com.siyoumi.util.XReturn;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.TimeUnit;

//redis相关
@TestClass(
        //runMethods = "testSearch"
)
@Slf4j
@RestController
@RequestMapping("/test/test_redis")
public class testRedis
        extends TestController {
    @TestFunc("加操作")
    public XReturn testRedisIncr() {
        Boolean ok = XRedis.getBean().increment("test|incr", 2, 10);

        XReturn r = XReturn.getR(0);
        r.setData("ok", ok);

        return r;
    }

    @TestFunc
    public XReturn testRedisLock() {
        return XRedisLock.tryLockFunc("test", k ->
        {
            XApp.sleep(1);
            return XReturn.getR(0);
        });

        //return getR();
    }

    @TestFunc
    public XReturn testRedisList() {

        XRedis redis = XRedis.getBean();

        //RListMultimap<Object, Object> testList = redis.getRedisson().getListMultimap("test_list", StringCodec.INSTANCE);
        //testList.put("aaa", "123");
        //testList.put("bbb", 456);
        //
        //RList<Object> aaa = testList.get("aaa");
        //getR().put("aaa", aaa);

        RDeque<String> abc = redis.getDeque("abc");
        //abc.add(XDate.toDateTimeString());
        //abc.push(XDate.toDateTimeString());
        //abc.addFirst("test");

        //Object pop = abc.poll();
        String s = abc.pollLast();
        getR().setData("a", s);

        return getR();
    }

    @TestFunc("删除测试")
    public XReturn testRedisDel() {
        RScript script = XRedis.getBean().getScript();

        String luaScript = "local currValue = redis.call('get', KEYS[1]); " +
                "if currValue == ARGV[1] then " +
                "redis.call('del', KEYS[1]); " +
                "return 1; " +
                "end;" +
                "return 0; ";
        //luaScript = "redis.call('set',KEYS[1], ARGV[1]); return redis.call('get', KEYS[1]); ";

        List<Object> keys = Collections.singletonList("test123");
        Boolean ok = script.eval(RScript.Mode.READ_WRITE, luaScript, RScript.ReturnType.BOOLEAN, keys, "123");
        //String ok = script.eval(RScript.Mode.READ_WRITE, luaScript, RScript.ReturnType.VALUE, keys, "aaaa");
        getR().setData("del", ok);

        XRedis.getBean().deleteByPattern("abc*");

        return getR();
    }


    @TestFunc("列表使用输出全部")
    public XReturn testRedisListGet() {
        String key = SysConfig.getIns().getEnv() + "|task";
        log.debug("key:{}", key);
        RMap<String, String> list = XRedis.getBean().getList(key);

        List<Map<String, Object>> listData = new LinkedList<>();
        list.forEach((k, v) -> {
            Map<String, Object> data = new HashMap<>();
            data.put(k, v);

            listData.add(data);
        });

        getR().setData("list", listData);

        return getR();
    }


    @TestFunc("加减测试")
    public XReturn testRedisInc() {
        XReturn r = XReturn.getR(0);

        Long inc = XRedis.getBean().increment("test", 2L);

        r.setData("inc", inc);
        r.setData("dec1", XRedis.getBean().decrement("test"));
        r.setData("dec2", XRedis.getBean().decrement("test"));
        r.setData("dec3", XRedis.getBean().decrement("test"));

        return r;
    }

    @SneakyThrows
    @TestFunc("信号量用法")
    public XReturn testSemaphore() {

        RPermitExpirableSemaphore semaphore = XRedis.getBean().getExpirableSemaphore("semaphore");
        //semaphore.release(10);
        //boolean b = semaphore.tryAcquire(2);
        String b = semaphore.tryAcquire(3, TimeUnit.SECONDS);

        XReturn r = XReturn.getR(0);
        r.setData("semaphore", b);

        return r;
    }

    @TestFunc("lua判断")
    public XReturn testLimit() {
        XReturn r = XReturn.getR(0);

        RScript script = XRedis.getBean().getScript();
        String luaScript = "local currValue = redis.call('get', KEYS[1]); " +
                //key未赋值
                "if not currValue then " +
                "redis.call('incr', KEYS[1]); " +
                "return 1; " +
                "end;" +

                "if tonumber(currValue) < tonumber(ARGV[1]) then " +
                "redis.call('incr', KEYS[1]); " +
                "return 1; " +
                "end;" +

                "return 0; ";

        List<Object> keys = Collections.singletonList("test123");
        boolean ok = script.eval(RScript.Mode.READ_WRITE, luaScript, RScript.ReturnType.BOOLEAN, keys, "3");

        r.setData("lua", ok);

        return r;
    }
}
